﻿/****************************************
* File description: main.qml
* CurrentVersion: 1.0.0
* Author: JNN
* Date: 2024-07-01
*  -----
* Copyright by 博坤生物
*****************************************/

import QtQuick 2.12
import QtQuick.Window 2.12

import "./components"
import "./pageComponents"
import "./report"
import "./promptBox"
import "./licenseManager"
import "./chromatogram"
import CCustomClass 1.0

Window {

    id: mainwindow

    visible: false
    width: 1700*dp
    height: 1000*dp

    minimumWidth: 1600*dp
    minimumHeight: 960*dp

    title: qsTr("EZ Studio V1.1")


    property real dp: config.dp


    Config{
        id: config
    }
    FuncTools{
        id: funcTools
    }

    CustomPopupBoxError{
        id: box_error_cannotCloseMainWindow
        box_text: "实验正在运行中，请先停止实验再退出软件"
//        onAccepted: {
//            CTools.exitProgram()
//        }
    }
    CustomPopupBoxWarning{
        id: box_warning_closeMainWindow
        box_text: "确认退出软件吗？"
        onAccepted: {

            CCamera.deleteCamera("CameraPurify")
            CCamera.deleteCamera("CameraPractice")
            CCamera.deleteCamera("CameraShifting")

            CTools.exitProgram()
        }
    }
    Splash{
        onHided: {
            mainwindow.visible=true
        }
    }

    property int gAppModule: 0     // 0-全显示  1-123模块 2-4模块


    // 一些状态信息
    property var gStateOp: gStateOp_
    property var gStateExp: gStateExp_
    property var gStateReset: gStateReset_
    property var gStateCamera: gStateCamera_
    StateExp{
        id: gStateExp_       // 实验信息
    }StateReset{
        id: gStateReset_     // 复位信息
    }StateOperate{
        id: gStateOp_        // 动画那块的单步执行按钮
    }StateCamera{
        id: gStateCamera_
    }



    onClosing: {
        if(gExpIsRunning === 1){
            box_error_cannotCloseMainWindow.show()
            close.accepted = false
        }else{
            box_warning_closeMainWindow.show()
            close.accepted = false
        }
    }


    color: "#F7F7FA"
    Image{
        anchors.fill: parent
        source: "qrc:/picture/bcg.jpg"
        visible: gPageIdx === 0
        opacity: 0.5
    }


    PreferenceSettings{
        id:preset
        onClosing:{
            console.log("系统设置关闭")
            gIsShowPrefSettings = false
            if(gExpIsRunning === 0){     // 实验未运行时，根据实验配置刷新
                // 刷新可选项
                pageExpMain.updateExpModel()
                pageExp1.updateExpModel()
                pageExp2.updateExpModel()
                pageExp3.updateExpModel()
                pageExp4.updateExpModel()
                if(gPageIdx===1)    pageExp1.updateLogInfo()
                if(gPageIdx===2)    pageExp2.updateLogInfo()
                if(gPageIdx===3)    pageExp3.updateLogInfo()
                if(gPageIdx===4)    pageExp4.updateLogInfo()
            }
            // 刷新主页配置
            refreshModuleConfig()

            // 刷新耗材配置
            CAnimationPurify.setConsumableName(gStateExp.consumableName);
            CAnimationPurify.updateColor(gStateExp.singleMethod_4)
        }
    }

    function refreshModuleConfig(){

        // 刷新模块的状态
        var value = CExeConfig.getMaskingInformation()
        if(value[0]==="1"&&value[1]==="0"){
            gAppModule = 1
        }else if(value[0]==="0"&&value[1]==="1"){
            gAppModule = 2
        }else{
            gAppModule = 0
        }

        // 刷新转盘的状态
        gCollectContainer = CMaintenance.getComponentUseStatus("4", "8")        // 1使用 0不使用
        console.log("转盘的状态", gCollectContainer)

        // 刷新两种机型的状态
        gShiftingMaching = 2 - CMaintenance.getComponentUseStatus("3", "11")

        // 刷新是否有活检
        gHasRadioBar = CMaintenance.getComponentUseStatus("3", "8")

    }
    onGShiftingMachingChanged: {
        CAnimationShifting.setMachineType(gShiftingMaching)
    }

    property int gPageIdx: 0                     // 当前页面 （前端存）

    // 实验状态
    property int gExpIsRunning: 0          // 是否处于运行实验状态 0空闲 1运行
    property int gExpIsFailure: 0          // 是否处于故障状态 0无故障 1流程故障 2并发故障 3都有
    property int gExpIsFailurePause: 0     // 是否处于因为故障造成的暂停状态 0暂停 1不暂停
    property int gExpIsPause: 0            // 0不暂停 1暂停
    property int gExpIsExecOperate: 0      // 0在执行 1不在执行
    function initExpStatus(){
        gExpIsRunning = 0
        gExpIsFailure = 0
        gExpIsFailurePause = 0
        gExpIsPause = 0
        gExpIsExecOperate = 0
    }

    property bool gPauseNeedPassword: false
    property bool gConnectStatus: false          // 通信状态
    property bool gSpeechStatus: false           // 语音模块状态


    property bool gIsWaiting: false              // 是否处于等待状态（只是有个小显示，没别的影响）
    property bool gIsAirPumping: false           // 是否处于气泵状态
    property bool gIsWaterPumping: false         // 是否处于水泵状态

    property int gCollectContainer: 0            // 纯化模式 0显示转盘 1显示蠕动泵
    property int gHasRadioBar: 1                 // 是否有活检 0无 1有
    property int gShiftingMaching: 2             // 1原机型 2新机型


    onGConnectStatusChanged: {

        if(gIsShowPrefSettings && gConnectStatus === false) { return }       // 临时-打开系统设置时不接收故障信号

        // 网络连接状态从true变为false时，报网络连接异常
        if(gConnectStatus === false){
            // 如果已有报错里面没有设备通信异常，添加一条设备通信异常消息
            let hasConnectFailureInfo = false
            for(let i = 0; i < box_failureInfo2.failureInfoList.length; i ++){
                if(box_failureInfo2.failureInfoList[i][0] === "设备连接通信异常"){
                    hasConnectFailureInfo = true
                }
            }
            if(!hasConnectFailureInfo){
                if(gExpIsRunning){
                    if(gStateExp.isUnion){
                        box_failureInfo2.failureInfoList.push(["设备连接通信异常", "流程+并发"])
                    }else{
                        box_failureInfo2.failureInfoList.push(["设备连接通信异常", "流程"])
                    }
                }else{
                    box_failureInfo2.failureInfoList.push(["设备连接通信异常", "流程"])
                }
            }

            if(gExpIsRunning === 1){       // 运行中
                box_failureInfo2.showContinueButton = 0
                if(gStateExp.isUnion){
                    gExpIsFailure = 1 | 2
                }else{
                    gExpIsFailure = 1
                }
                gExpIsFailurePause = 1
            }else{
                gExpIsFailure
                box_failureInfo2.showContinueButton = 2
            }
            box_failureInfo2.failureInfoListChanged()
            box_failureInfo2.show()
        }

    }


    // 调试用
    property bool showDebug: false
    property bool isCheckConsumableCode: false

    property bool gIsShowPrefSettings: false
    property var  gModuleName: ["主页", "放靶", "打靶", "转靶", "纯化"]

    Timer{       // 运行时的计时器
        id: timer_running
        running: gExpIsRunning === 1 && gExpIsFailurePause===0
        interval: 1000
        repeat: true
        onTriggered: {

            if(gExpIsFailurePause === 1){        // 发生故障时，所有计时都暂停
                return
            }

            if(gExpIsRunning === 1 && gExpIsPause === 0){
                gStateExp.expRemainTime = Math.max(gStateExp.expRemainTime-1, 0)
                gStateExp.expRunningTime += 1
            }else if(gExpIsRunning === 1 && gExpIsPause === 1){
                gStateExp.expPauseTime ++       // 暂停的计时器
            }
            if(gIsWaiting){
                gStateExp.expWaitTime ++        // 等待的计时器
            }

            // 不处于暂停状态时，冷却和干燥的计时器累加(待定)
            if((!gIsWaiting) && (gExpIsPause===0)){
                if(gIsAirPumping){
                    gStateExp.expAirPumpTime = Math.max(gStateExp.expAirPumpTime - 1, 0)
                }
                if(gIsWaterPumping){
                    gStateExp.expWaterPumpTime = Math.max(gStateExp.expWaterPumpTime - 1, 0)
                }
            }
        }
    }

    signal sigExportReportWithChrom()
    function toDoEndExperiment(){

        initExpStatus()

        // 自动打印报告
        if(CReport.getAutoExport()){
            CReport.setReportIdx(-1)        // 更新为最新报告
            // 导出能谱图图片和导出报告放到能谱图那边调用
            sigExportReportWithChrom()
        }
        CChromManager.onEndExperiment()     // 关闭能谱图数据获取
        box_expFinish.show()                // 显示跳转弹窗
        gIsWaiting = false                  // 取消等待状态
        gIsAirPumping = false
        gIsWaterPumping = false
        gStateExp.initModuleStatus()        // 清空小条条状态信息
        gStateExp.isUnion = false       // 清除并发状态

        // 复位动画那块的按钮

        // 清空活检浓度
        gStateExp.hoJianConc = "--"

        // 清空故障信息并关闭故障弹窗
        box_failureInfo2.failureInfoList = []
        box_failureInfo2.showContinueButton = 0
        box_failureInfo2.close()
    }

    function toDoStartExperiment(){

    }

    function resetExperimentInfo(){

        gStateExp.resetStatusAfterExperiment()
        CAnimationPurify.reset()
        CAnimationPractice.reset()
        CAnimationShifting.reset()
        CChromManager.clearChart()
    }

    // 实验状态处理
    Connections{
        target: CSignal
        // 实验状态
        onExperimentStatus:{

            console.log("【ExperimentStatus】更新", "type:", type, "status:", status, "msg", msg)
            if(type.toString() === "0"){           // 结束实验
                toDoEndExperiment()
            }else if(type.toString() === "1"){     // 启动实验-开始
                if(status.toString() === "0"){
                    box_opStartExp.show()
                    box_opStartExp.startWait02()
                }else if(status.toString() === "1"){          // 启动实验-成功
                    gExpIsRunning = 1
                    // 清空故障状态（大概）
                    box_failureInfo2.failureInfoList = []
                    box_failureInfo2.showContinueButton = 0
                    // 获取时间信息
                    gStateExp.expRunningTime = 0
                    gStateExp.expRemainTime = CGetMessageInterface.getExperimentTotalTime()
                    gStateExp.expTotalTime = CGetMessageInterface.getExperimentTotalTime()
                    // 初始化模块状态
                    gStateExp.initModuleStatus()
                    if(gStateExp.selectedExpType === 0){
//                        gPageIdx = 1
                    }else{
                        gPageIdx = gStateExp.selectedExpType
                    }
                    CChromManager.onStartExperiment()     // 开启能谱图数据获取
                    CBarCode.startExpWithCode(gStateExp.consumableCode)

                    // 当前正在运行的模块
                    gStateExp.moduleStatus[gPageIdx] = 2
                    gStateExp.moduleStatusChanged()
                    box_opStartExp.close()
                    box_opStartExp.finishWait()
                }else if(status.toString() === "2"){        // 启动实验失败
                    box_opStartExp.failStart(msg)
                }


            }else if(type.toString() === "2"){     // 停止实验
                if(status.toString() === "0"){
                    box_opEndExp.show()
                    box_opEndExp.startWait02()
                }else{
                    toDoEndExperiment()
                    box_opEndExp.close()
                    box_opEndExp.finishWait()
                }
            }else if(type.toString() === "3"){     // 暂停 status=0开始停止
                if(status.toString() === "0"){  // 开始暂停
                    box_opPauseExp.show()
                    box_opPauseExp.startWait02()
                }else if(status.toString() === "1"){   // 完成暂停
                    box_opPauseExp.close()
                    box_opPauseExp.finishWait()
                    gStateExp.expPauseType = 0
                    gStateExp.expPauseTime = 0
                    gExpIsPause = 1
                }else if(status.toString() === "2"){   // 能谱图触发的暂停
                    box_opPauseExp.close()
                    box_opPauseExp.finishWait()
                    gStateExp.expPauseType = 1
                    gStateExp.expPauseTime = 0
                    gExpIsPause = 1
                    box_chromPause.show()
                }else if(status.toString() === "3"){    // 活性检测触发的暂停
                    box_opPauseExp.close()
                    box_opPauseExp.finishWait()
                    gStateExp.expPauseType = 2
                    gStateExp.expPauseTime = 0
                    gExpIsPause = 1
                }
            }else if(type.toString() === "5"){     // status=0开始等待 =1结束等待
                console.log("接收到等待信号", status)
                if(status.toString()==="0"){
                    gIsWaiting = true
                }else{
                    gIsWaiting = false
                    gStateExp.expWaitTime = 0
                }
            }else if(type.toString() === "4"){     // 继续
                if(status.toString() === "0"){
                    box_opContinueExp.show()
                    box_opContinueExp.startWait02()
                }else{
                    box_opContinueExp.close()
                    box_opContinueExp.finishWait()
                    gExpIsPause = 0
                }
                gExpIsPause = 0
            }else if(type.toString() === "6"){     // 急停
                toDoEndExperiment()
            }else if(type.toString() === "7"){     // 故障后继续实验
                gExpIsFailurePause = 0
            }
        }
        // 需要输入密码的暂停
        onSendPauseConfirmation:{
            box_opPauseExp.close()
            box_opPauseExp.finishWait()
            gStateExp.expPauseTime = 0
            gPauseNeedPassword = true
            gExpIsPause = 1
        }
        // 设备状态
        onCommunicationStatus: {        // status 0连接成功 1通信断开
            gConnectStatus = (status === 0)
        }
        onNeedReset:{           // 不知道什么时候出现的弹窗，提示用户复位设备
            box_needReset.show()

        }
        // 通讯状态
        onVoiceAssistant: {
            gSpeechStatus = (status === 0)
        }
        // 复位状态
        onSendResetMsg: {           // status 开始复位 0 复位完成       serial 序号
            console.log("复位状态变化", status, serial)       // 1 复位中  0 复位完成
            if(gIsShowPrefSettings) { return }  // 临时-打开系统设置时不接收复位信号
            if(status === "1"){         // 1复位中
                gStateReset.startSerial(serial)
                gExpIsExecOperate = 1
                box_resetting.show()
            }else{                      // 0复位完成
                gStateReset.finishSerial(serial)
                if(gStateReset.checkResetState()){
                    gExpIsExecOperate = 0
//                    box_resetting.show()
                }
            }
        }
        onSendSyringRunMsg: {       // 注射器正在复位，禁止下一步操作
            if(status === "1"){
                toast.show(serial+"号注射器正在执行中,请耐心等待", 1)
            }
        }
        // 实验中某一步骤响应超时
        onReceiveMsgOutTime: {
            console.log("步骤响应超时")
            box_forceStop.show()
        }

        // 故障
        onSendErrorMsg: {                // errorInfo, methodInfo, errorModule=1234模块 1.5 2.5 3.5连线


            if(gIsShowPrefSettings) { return }  // 临时-打开系统设置时不接收故障信号

            console.log("sendErrorMsg", errorInfo, methodInfo, errorType)

            // 判断故障类型
            if(gExpIsRunning === 1){
                gExpIsFailure = gExpIsFailure | (errorType+1)
                // 流程和并发同时执行时，当只有一个故障时，给另一个故障也报错
                if(gStateExp.isUnion){
                    if(errorType === 0 && ((gExpIsFailure&2)===0)){           // 报出来的是流程故障，并且当前没有并发故障时，把并发故障也干停了
                        box_failureInfo2.failureInfoList.push(["由于流程实验出现故障，并发实验已暂停", "并发"])
                        gExpIsFailure = gExpIsFailure | 2
                    }else if(errorType === 1 && ((gExpIsFailure&1)===0)){
                        box_failureInfo2.failureInfoList.push(["由于并发实验出现故障，流程实验已暂停", "流程"])
                        gExpIsFailure = gExpIsFailure | 1
                    }
                }
                gExpIsFailurePause = 1
            }

            if(methodInfo === "是"){
                box_failureInfo2.showContinueButton = Math.max(box_failureInfo2.showContinueButton, 0)
            }else if(methodInfo === "否"){
                box_failureInfo2.showContinueButton = 1
            }else{
                box_failureInfo2.showContinueButton = 2
            }
            // 刷新故障信息
            let errorList = errorInfo.split("\n")
            for(let i = 0; i < errorList.length; i ++){
                if(errorList[i] !== "")
                    box_failureInfo2.failureInfoList.push([errorList[i], errorType===0?"流程":"并发"])
            }
            box_failureInfo2.failureInfoListChanged()
            box_failureInfo2.show()

            if(box_failureInfo2.showContinueButton === 2){           // 非实验状态，不变红

            }else{
                CAnimation.handleErrorMsg(errorInfo, Number(errorModule))       // 故障信息传递给动画
                if(errorModule.length === 1){
                    if(Number(errorModule)===0){
                        // 如果传0不变红
                    }else{
//                        gStateExp.moduleStatus[Number(errorModule)] = -1            // 上面的状态变红
//                        gStateExp.moduleStatusChanged()
                        // 这块的红色弃用了，就这样吧
                    }
                }else{
                    gStateExp.moduleConnectStatus[Number(errorModule)-0.5] = -1
                    gStateExp.moduleStatusChanged()
                }
            }
        }
        // 步骤号刷新
        onRefExperimentLog: {       // step
            console.log("步骤号刷新", step)
            gStateExp.expStep = step
            if(gPageIdx===1) pageExp1.updateLogInfo()
            if(gPageIdx===2) pageExp2.updateLogInfo()
            if(gPageIdx===3) pageExp3.updateLogInfo()
            if(gPageIdx===4) pageExp4.updateLogInfo()
        }
        // 某个模块的状态变为已完成
        onModuleFinish:{        // module
            gStateExp.moduleStatus[Number(module)] = 3
            gStateExp.moduleStatusChanged()
        }
        // 当前正在执行的模块变化
        onModuleCurrent:{      // module
            console.log("onModuleCurrent", module)
            toast.show("切换至" + gModuleName[Number(module)] + "模块运行", 0)
            for(let i = 1; i <= 4; i ++){           // 之前正在运行的模块状态变更为待执行
                if(gStateExp.moduleStatus[i] === 2){
                    gStateExp.moduleStatus[i] = 1
                }
            }
            gStateExp.moduleStatus[Number(module)] = 2
            gStateExp.moduleStatusChanged()
            gPageIdx = Number(module)
        }
        // 是否在执行并发变化
        onUnionStatus: {            // 0不并发 1并发
            if(status === 0){
                gStateExp.isUnion = false
            }else{
                gStateExp.isUnion = true
            }
        }

        // 主页单步执行指令下发
        onStepRunningStatus: {
            // 迁移至StateOperate中处理
        }
        // 实验恢复
        onSendExistExp: {           // int module,int step,QString actionInfo,int nextModule,int nextStep,QString nextActionInfo
            box_expRescue.module1 = module
            box_expRescue.module2 = nextModule
            box_expRescue.step1 = step
            box_expRescue.step2 = nextStep
            box_expRescue.stepInfo1 = actionInfo
            box_expRescue.stepInfo2 = nextActionInfo
            box_expRescue.show()
        }
        // 后端查询实验信息（用于语音助手）
        onGetExperimentInfo: {
            CGetMessageInterface.setExpBaseInfo(gStateExp.getExpUserInfo())        // 设置用户信息
        }


    }
    // 能谱图数据
    Connections{
        target: CSignal
        onSendCpsData: {
            CChromManager.appendNewPoint(cpsData)
        }
    }
//    Timer{                // 测试能谱图
//        repeat: true
//        running: true
//        interval: 8
//        property int trigTimes: 0
//        onTriggered: {
//            console.log(trigTimes)
//            trigTimes ++
//            if(trigTimes === 50){
//                CChromManager.onStartExperiment()
//            }
//            let base = 1000
//            if(trigTimes > 1000){
//                base = -99000 + trigTimes * 100
//                console.log(1, base)
//            }
//            if(trigTimes > 1200){
//                base = 21000 - (trigTimes-1200)*100
//                console.log(2, base)
//            }
//            if(base < 1000){
//                base = 1000
//                console.log(3, base)
//            }

//            CChromManager.appendNewPoint(base + Math.random() * 200)
//        }
//    }


    Connections{
        target: CExeConfig
        onMaskingInformation:{                  // 屏蔽模块
            refreshModuleConfig()

        }
    }
    onVisibleChanged: {
        refreshModuleConfig()
    }

    onGAppModuleChanged: {
        gStateExp.initExpInfo()
        if(gAppModule === 2){
            gPageIdx = 4
        }else{
            gPageIdx = 0
        }
    }


    Rectangle{      // 步骤条背景变成白色的了
        height: layout_expPage.y
        width: parent.width
        opacity: 0.6
    }
    StepLine2{
        id: stepLine
        visible: gAppModule === 0 || gAppModule === 1       // 模块屏蔽
//        x: 0.5*(parent.width - width); y: 20*dp
        onTabPage: {
            if(gStateExp.expName === "" && idx !== 0){
                box_error_common.box_text = "实验名称不能为空"
                box_error_common.show()
                gPageIdx = 0
                return
            }
            gPageIdx = idx
        }
    }


    Item{
        id: layout_expPage
        x: 10*dp
//        y: stepLine.visible ? stepLine.y*2 + stepLine.height : 0      // 适配stepline原版
        y: stepLine.visible ? stepLine.height : 0               // 适配新版stepline
        width: parent.width - 2*x
        height: parent.height - y - x - deviceCheckInfo.height
        PageExpMain{
            id: pageExpMain
            visible: gPageIdx === 0
        }PageExp1{
            id: pageExp1
            visible: gPageIdx === 1
        }PageExp2{
            id: pageExp2
            visible: gPageIdx === 2
        }PageExp3{
            id: pageExp3
            visible: gPageIdx === 3
        }PageExp4{
            id: pageExp4
            visible: gPageIdx === 4
        }
        states: [           // 页面状态显隐以及动画控制
            State{
                name: "showPageMain"
                when: gPageIdx === 0
                PropertyChanges {  target: pageExpMain;  visible: true;   opacity: 1  }
                PropertyChanges {  target: pageExp1;     visible: false;  opacity: 0  }
                PropertyChanges {  target: pageExp2;     visible: false;  opacity: 0  }
                PropertyChanges {  target: pageExp3;     visible: false;  opacity: 0  }
                PropertyChanges {  target: pageExp4;     visible: false;  opacity: 0  }
            },State{
                name: "showPage1"
                when: gPageIdx === 1
                PropertyChanges {  target: pageExpMain;  visible: false;  opacity: 0  }
                PropertyChanges {  target: pageExp1;     visible: true;   opacity: 1  }
                PropertyChanges {  target: pageExp2;     visible: false;  opacity: 0  }
                PropertyChanges {  target: pageExp3;     visible: false;  opacity: 0  }
                PropertyChanges {  target: pageExp4;     visible: false;  opacity: 0  }
            },State{
                name: "showPage2"
                when: gPageIdx === 2
                PropertyChanges {  target: pageExpMain;  visible: false;  opacity: 0  }
                PropertyChanges {  target: pageExp1;     visible: false;  opacity: 0  }
                PropertyChanges {  target: pageExp2;     visible: true;   opacity: 1  }
                PropertyChanges {  target: pageExp3;     visible: false;  opacity: 0  }
                PropertyChanges {  target: pageExp4;     visible: false;  opacity: 0  }
            },State{
                name: "showPage3"
                when: gPageIdx === 3
                PropertyChanges {  target: pageExpMain;  visible: false;  opacity: 0  }
                PropertyChanges {  target: pageExp1;     visible: false;  opacity: 0  }
                PropertyChanges {  target: pageExp2;     visible: false;  opacity: 0  }
                PropertyChanges {  target: pageExp3;     visible: true;   opacity: 1  }
                PropertyChanges {  target: pageExp4;     visible: false;  opacity: 0  }
            },State{
                name: "showPage4"
                when: gPageIdx === 4
                PropertyChanges {  target: pageExpMain;  visible: false;  opacity: 0  }
                PropertyChanges {  target: pageExp1;     visible: false;  opacity: 0  }
                PropertyChanges {  target: pageExp2;     visible: false;  opacity: 0  }
                PropertyChanges {  target: pageExp3;     visible: false;  opacity: 0  }
                PropertyChanges {  target: pageExp4;     visible: true;   opacity: 1  }
            }
        ]

        transitions: [
            Transition {
                // 移除 targets 属性，通过状态变化自动匹配
                NumberAnimation {
                    properties: "opacity"
                    duration: 300
                    easing.type: Easing.InOutQuad
                }
                // 切换时先隐藏所有其他页面
                onRunningChanged: {
                    if (!running) return;
                    // 手动获取所有页面组件列表
                    const pages = [pageExp1, pageExp2, pageExp3, pageExp4, pageExpMain];
                    for (let i = 0; i < pages.length; i++) {
                        let page = pages[i];
                        // 非当前激活状态的页面设置为透明
                        if (!page.visible || (page.visible && page.opacity < 1)) {
                            page.opacity = 0;
                        }
                    }
                }
            }
        ]


    }
    DeviceCheckInfoLine{
        id: deviceCheckInfo
        y: layout_expPage.y + layout_expPage.height + 10*dp
    }


    CustomPopupBoxError{        // 通用的错误弹窗提示
        id: box_error_common
    }CustomPopupBoxSucceed{
        id: box_succeed_common
    }

    CustomToast{
        id: toast
        y: 120*dp
        x: (parent.width - width) * 0.5
    }


    // 各种弹窗们 ==============================================>
    BoxFailureInfo{
        id: box_failureInfo
    }
    BoxFailureInfo_plus{
        id: box_failureInfo2
    }
    BoxExpFinish{
        id: box_expFinish
    }
    BoxResetting{
        id: box_resetting
    }
    BoxOperating{
        id: box_operating
    }
    BoxPrinter{
        id: box_printer
    }
    BoxExpRescue{
        id: box_expRescue
    }
    BoxOpStartExp{
        id: box_opStartExp
    }
    BoxForceStop{
        id: box_forceStop
    }
    BoxTimeWaterAirPump{
        id: box_waterAir
    }
    BoxOpEndExp{
        id: box_opEndExp
    }
    BoxOpContinueExp{
        id: box_opContinueExp
    }
    BoxOpPauseExp{
        id: box_opPauseExp
    }
    BoxNeedReset{
        id: box_needReset
    }
//    BoxExportImage{
//        id: box_exportImage
//    }

    CustomPopupBoxWarning{
        id: box_chromPause
        title: "提示"
        rejectedText: "关闭"
        showAcceptedButton: false
        box_text: "当前能谱检测为手动模式，能谱信号达到要求后请点击[继续]，收集产物"
        overlayColor: "#55000000"
    }

    Debugger{
    }
    MouseArea{      // 隐藏前端页面调试信息
        property int doubleClickedCount: 0
        height: 30*dp; width: 30*dp
        onDoubleClicked: {
            doubleClickedCount = (doubleClickedCount+1)%5
            if(doubleClickedCount === 4){
                showDebug = true
            }else{
                showDebug = false
            }
        }
    }

    BoxLicense{
        id: license
        z: 100
    }


}
